package org.bozo.im.service.protocols.xmpp.stanza;

import java.util.Hashtable;

import org.bozo.im.service.protocols.xmpp.util.namespace.Namespace;

public enum Stanza {

	BIND_BIND("bind", Namespace.BIND),
	BIND_JID("jid", Namespace.BIND),
	
	CAPABILITIES_C("c", Namespace.CAPABILITIES),
	
	ERROR_ERROR("error", Namespace.ERROR),
	ERROR_TEXT("text", Namespace.ERROR),
	
	JABBER_CLIENT_IQ("iq", Namespace.JABBER_CLIENT),
	JABBER_CLIENT_PRESENCE("presence", Namespace.JABBER_CLIENT),
	JABBER_CLIENT_SHOW("show", Namespace.JABBER_CLIENT),

	ROSTER_ITEM("item", Namespace.ROSTER),
	ROSTER_QUERY("query", Namespace.ROSTER),

	SASL_CHALLENGE("challenge", Namespace.SASL),
	SASL_MECHANISM("mechanism", Namespace.SASL),
	SASL_MECHANISMS("mechanisms", Namespace.SASL),
	SASL_SUCCESS("success", Namespace.SASL),
	
	SESSION_SESSION("session", Namespace.SESSION),
	
	STARTTLS_PROCEED("proceed", Namespace.STARTTLS),
	STARTTLS_REQUIRED("required", Namespace.STARTTLS),
	STARTTLS_STARTTLS("starttls", Namespace.STARTTLS),

	STREAM_FEATURES("features", Namespace.STREAM),
	STREAM_STREAM("stream", Namespace.STREAM);
	
	private static Hashtable<StanzaDescription, Stanza> mStanzas;
	
	static {
		mStanzas = new Hashtable<StanzaDescription, Stanza>();
		addStanza(BIND_BIND);
		addStanza(BIND_JID);
		
		addStanza(CAPABILITIES_C);
		
		addStanza(ERROR_ERROR);
		addStanza(ERROR_TEXT);
		
		addStanza(JABBER_CLIENT_IQ);
		addStanza(JABBER_CLIENT_PRESENCE);
		addStanza(JABBER_CLIENT_SHOW);

		addStanza(ROSTER_ITEM);
		addStanza(ROSTER_QUERY);

		addStanza(SASL_CHALLENGE);
		addStanza(SASL_MECHANISM);
		addStanza(SASL_MECHANISMS);
		addStanza(SASL_SUCCESS);
		
		addStanza(SESSION_SESSION);
		
		addStanza(STARTTLS_PROCEED);
		addStanza(STARTTLS_REQUIRED);
		addStanza(STARTTLS_STARTTLS);
		
		addStanza(STREAM_FEATURES);
		addStanza(STREAM_STREAM);
	}
	
	private static void addStanza(Stanza pStanza) {
		mStanzas.put(new StanzaDescription(pStanza.getNamespace(), pStanza.getName()), pStanza);
	}
	
	public static Stanza valueOf(String pName, Namespace pNamespace) {
		return mStanzas.get(new StanzaDescription(pNamespace, pName));
	}

	public static Stanza valueOf(String pName, String pNamespace) {

		Stanza lRes = null;
		
		Namespace lNamespace = Namespace.valueOfNamespace(pNamespace);
		
		if (lNamespace != null)
			lRes = valueOf(pName, lNamespace);
		
		return lRes;
	}
	
	private StanzaDescription mDescription;
	
	private Stanza(String pName, Namespace pNamespace) {
		mDescription = new StanzaDescription(pNamespace, pName);
	}

	public String getName() {
		return mDescription.mName;
	}
	
	public Namespace getNamespace() {
		return mDescription.mNamespace;
	}
	
	private static class StanzaDescription {
		Namespace mNamespace;
		String mName;
		
		public StanzaDescription(Namespace pNamespace, String pName) {
			mName = pName;
			mNamespace = pNamespace;
		}
		
		@Override
		public boolean equals(Object pObj) {
			
			return (pObj instanceof StanzaDescription
					&& ((StanzaDescription)pObj).mNamespace == mNamespace
					&& ((StanzaDescription)pObj).mName.equals(mName));
		}
		
		@Override
		public int hashCode() {
			return mNamespace.hashCode() & mName.hashCode();
		}
	}
}
